/*
Copyright (C) 2019-2022 JingWeiZhangHuai <jingweizhanghuai@163.com>
Licensed under the Apache License, Version 2.0; you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
*/
#include "morn_util.h"
 
#ifndef LITTLE_ENDIAN
#define LITTLE_ENDIAN 1234
#endif

#ifndef BIG_ENDIAN
#define BIG_ENDIAN 4321
#endif

// const uint8_t morn_endian_a[2]={0,1};
// #define mEndian() ((1!=*((uint16_t *)morn_endian_a))?LITTLE_ENDIAN:BIG_ENDIAN)

uint8_t morn_reverse_data[256]={0,128,64,192,32,160,96,224,16,144,80,208,48,176,112,240,8,136,72,200,40,168,104,232,24,152,88,216,56,184,120,248,4,132,68,196,36,164,100,228,20,148,84,212,52,180,116,244,12,140,76,204,44,172,108,236,28,156,92,220,60,188,124,252,2,130,66,194,34,162,98,226,18,146,82,210,50,178,114,242,10,138,74,202,42,170,106,234,26,154,90,218,58,186,122,250,6,134,70,198,38,166,102,230,22,150,86,214,54,182,118,246,14,142,78,206,46,174,110,238,30,158,94,222,62,190,126,254,1,129,65,193,33,161,97,225,17,145,81,209,49,177,113,241,9,137,73,201,41,169,105,233,25,153,89,217,57,185,121,249,5,133,69,197,37,165,101,229,21,149,85,213,53,181,117,245,13,141,77,205,45,173,109,237,29,157,93,221,61,189,125,253,3,131,67,195,35,163,99,227,19,147,83,211,51,179,115,243,11,139,75,203,43,171,107,235,27,155,91,219,59,187,123,251,7,135,71,199,39,167,103,231,23,151,87,215,55,183,119,247,15,143,79,207,47,175,111,239,31,159,95,223,63,191,127,255};

__thread uint8_t morn_crc_buff[1024];
uint8_t *ReverseData(uint8_t *in,int size)
{
    uint8_t *out=(size<=1024)?morn_crc_buff:mMalloc(size);
    for(int i=0;i<size;i++)
        out[i]=morn_reverse_data[in[i]];
    return out;
}

#define Reverse8(Data) (morn_reverse_data[Data])
uint16_t Reverse16(uint32_t data)
{
    uint16_t data16=data&0x0FFFF;uint8_t *p=(uint8_t *)(&data16);
    uint16_t rst;                uint8_t *r=(uint8_t *)(&rst   );
    r[0]=morn_reverse_data[p[1]];r[1]=morn_reverse_data[p[0]];
    return rst;
}
uint32_t Reverse32(uint32_t data)
{
    uint32_t rst;
    uint8_t *p=(uint8_t *)(&data);
    uint8_t *r=(uint8_t *)(&rst );
    r[0]=morn_reverse_data[p[3]];r[1]=morn_reverse_data[p[2]];r[2]=morn_reverse_data[p[1]];r[3]=morn_reverse_data[p[0]];
    return rst;
}

struct HandleCRC
{
    int bit;
    int bit0;
    uint32_t poly;
    uint32_t init;
    uint32_t xor;
    int endian;
    int endian0;
    uint32_t *table;
    uint32_t table0[256];
};
void endCRC(struct HandleCRC *handle) {NULL;}
#define HASH_CRC 0xd161ac33
struct HandleCRC *morn_crc_handle = NULL;

uint32_t morn_crc32_table[ 256]={0x0,0x77073096,0xee0e612c,0x990951ba,0x76dc419,0x706af48f,0xe963a535,0x9e6495a3,0xedb8832,0x79dcb8a4,0xe0d5e91e,0x97d2d988,0x9b64c2b,0x7eb17cbd,0xe7b82d07,0x90bf1d91,0x1db71064,0x6ab020f2,0xf3b97148,0x84be41de,0x1adad47d,0x6ddde4eb,0xf4d4b551,0x83d385c7,0x136c9856,0x646ba8c0,0xfd62f97a,0x8a65c9ec,0x14015c4f,0x63066cd9,0xfa0f3d63,0x8d080df5,0x3b6e20c8,0x4c69105e,0xd56041e4,0xa2677172,0x3c03e4d1,0x4b04d447,0xd20d85fd,0xa50ab56b,0x35b5a8fa,0x42b2986c,0xdbbbc9d6,0xacbcf940,0x32d86ce3,0x45df5c75,0xdcd60dcf,0xabd13d59,0x26d930ac,0x51de003a,0xc8d75180,0xbfd06116,0x21b4f4b5,0x56b3c423,0xcfba9599,0xb8bda50f,0x2802b89e,0x5f058808,0xc60cd9b2,0xb10be924,0x2f6f7c87,0x58684c11,0xc1611dab,0xb6662d3d,0x76dc4190,0x1db7106,0x98d220bc,0xefd5102a,0x71b18589,0x6b6b51f,0x9fbfe4a5,0xe8b8d433,0x7807c9a2,0xf00f934,0x9609a88e,0xe10e9818,0x7f6a0dbb,0x86d3d2d,0x91646c97,0xe6635c01,0x6b6b51f4,0x1c6c6162,0x856530d8,0xf262004e,0x6c0695ed,0x1b01a57b,0x8208f4c1,0xf50fc457,0x65b0d9c6,0x12b7e950,0x8bbeb8ea,0xfcb9887c,0x62dd1ddf,0x15da2d49,0x8cd37cf3,0xfbd44c65,0x4db26158,0x3ab551ce,0xa3bc0074,0xd4bb30e2,0x4adfa541,0x3dd895d7,0xa4d1c46d,0xd3d6f4fb,0x4369e96a,0x346ed9fc,0xad678846,0xda60b8d0,0x44042d73,0x33031de5,0xaa0a4c5f,0xdd0d7cc9,0x5005713c,0x270241aa,0xbe0b1010,0xc90c2086,0x5768b525,0x206f85b3,0xb966d409,0xce61e49f,0x5edef90e,0x29d9c998,0xb0d09822,0xc7d7a8b4,0x59b33d17,0x2eb40d81,0xb7bd5c3b,0xc0ba6cad,0xedb88320,0x9abfb3b6,0x3b6e20c,0x74b1d29a,0xead54739,0x9dd277af,0x4db2615,0x73dc1683,0xe3630b12,0x94643b84,0xd6d6a3e,0x7a6a5aa8,0xe40ecf0b,0x9309ff9d,0xa00ae27,0x7d079eb1,0xf00f9344,0x8708a3d2,0x1e01f268,0x6906c2fe,0xf762575d,0x806567cb,0x196c3671,0x6e6b06e7,0xfed41b76,0x89d32be0,0x10da7a5a,0x67dd4acc,0xf9b9df6f,0x8ebeeff9,0x17b7be43,0x60b08ed5,0xd6d6a3e8,0xa1d1937e,0x38d8c2c4,0x4fdff252,0xd1bb67f1,0xa6bc5767,0x3fb506dd,0x48b2364b,0xd80d2bda,0xaf0a1b4c,0x36034af6,0x41047a60,0xdf60efc3,0xa867df55,0x316e8eef,0x4669be79,0xcb61b38c,0xbc66831a,0x256fd2a0,0x5268e236,0xcc0c7795,0xbb0b4703,0x220216b9,0x5505262f,0xc5ba3bbe,0xb2bd0b28,0x2bb45a92,0x5cb36a04,0xc2d7ffa7,0xb5d0cf31,0x2cd99e8b,0x5bdeae1d,0x9b64c2b0,0xec63f226,0x756aa39c,0x26d930a,0x9c0906a9,0xeb0e363f,0x72076785,0x5005713,0x95bf4a82,0xe2b87a14,0x7bb12bae,0xcb61b38,0x92d28e9b,0xe5d5be0d,0x7cdcefb7,0xbdbdf21,0x86d3d2d4,0xf1d4e242,0x68ddb3f8,0x1fda836e,0x81be16cd,0xf6b9265b,0x6fb077e1,0x18b74777,0x88085ae6,0xff0f6a70,0x66063bca,0x11010b5c,0x8f659eff,0xf862ae69,0x616bffd3,0x166ccf45,0xa00ae278,0xd70dd2ee,0x4e048354,0x3903b3c2,0xa7672661,0xd06016f7,0x4969474d,0x3e6e77db,0xaed16a4a,0xd9d65adc,0x40df0b66,0x37d83bf0,0xa9bcae53,0xdebb9ec5,0x47b2cf7f,0x30b5ffe9,0xbdbdf21c,0xcabac28a,0x53b39330,0x24b4a3a6,0xbad03605,0xcdd70693,0x54de5729,0x23d967bf,0xb3667a2e,0xc4614ab8,0x5d681b02,0x2a6f2b94,0xb40bbe37,0xc30c8ea1,0x5a05df1b,0x2d02ef8d};
uint32_t morn_crc16_table1[256]={0x0,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf,0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7,0x1081,0x108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e,0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876,0x2102,0x308b,0x210,0x1399,0x6726,0x76af,0x4434,0x55bd,0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5,0x3183,0x200a,0x1291,0x318,0x77a7,0x662e,0x54b5,0x453c,0xbdcb,0xac42,0x9ed9,0x8f50,0xfbef,0xea66,0xd8fd,0xc974,0x4204,0x538d,0x6116,0x709f,0x420,0x15a9,0x2732,0x36bb,0xce4c,0xdfc5,0xed5e,0xfcd7,0x8868,0x99e1,0xab7a,0xbaf3,0x5285,0x430c,0x7197,0x601e,0x14a1,0x528,0x37b3,0x263a,0xdecd,0xcf44,0xfddf,0xec56,0x98e9,0x8960,0xbbfb,0xaa72,0x6306,0x728f,0x4014,0x519d,0x2522,0x34ab,0x630,0x17b9,0xef4e,0xfec7,0xcc5c,0xddd5,0xa96a,0xb8e3,0x8a78,0x9bf1,0x7387,0x620e,0x5095,0x411c,0x35a3,0x242a,0x16b1,0x738,0xffcf,0xee46,0xdcdd,0xcd54,0xb9eb,0xa862,0x9af9,0x8b70,0x8408,0x9581,0xa71a,0xb693,0xc22c,0xd3a5,0xe13e,0xf0b7,0x840,0x19c9,0x2b52,0x3adb,0x4e64,0x5fed,0x6d76,0x7cff,0x9489,0x8500,0xb79b,0xa612,0xd2ad,0xc324,0xf1bf,0xe036,0x18c1,0x948,0x3bd3,0x2a5a,0x5ee5,0x4f6c,0x7df7,0x6c7e,0xa50a,0xb483,0x8618,0x9791,0xe32e,0xf2a7,0xc03c,0xd1b5,0x2942,0x38cb,0xa50,0x1bd9,0x6f66,0x7eef,0x4c74,0x5dfd,0xb58b,0xa402,0x9699,0x8710,0xf3af,0xe226,0xd0bd,0xc134,0x39c3,0x284a,0x1ad1,0xb58,0x7fe7,0x6e6e,0x5cf5,0x4d7c,0xc60c,0xd785,0xe51e,0xf497,0x8028,0x91a1,0xa33a,0xb2b3,0x4a44,0x5bcd,0x6956,0x78df,0xc60,0x1de9,0x2f72,0x3efb,0xd68d,0xc704,0xf59f,0xe416,0x90a9,0x8120,0xb3bb,0xa232,0x5ac5,0x4b4c,0x79d7,0x685e,0x1ce1,0xd68,0x3ff3,0x2e7a,0xe70e,0xf687,0xc41c,0xd595,0xa12a,0xb0a3,0x8238,0x93b1,0x6b46,0x7acf,0x4854,0x59dd,0x2d62,0x3ceb,0xe70,0x1ff9,0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330,0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0xf78};
uint32_t morn_crc16_table2[256]={0x0,0xc0c1,0xc181,0x140,0xc301,0x3c0,0x280,0xc241,0xc601,0x6c0,0x780,0xc741,0x500,0xc5c1,0xc481,0x440,0xcc01,0xcc0,0xd80,0xcd41,0xf00,0xcfc1,0xce81,0xe40,0xa00,0xcac1,0xcb81,0xb40,0xc901,0x9c0,0x880,0xc841,0xd801,0x18c0,0x1980,0xd941,0x1b00,0xdbc1,0xda81,0x1a40,0x1e00,0xdec1,0xdf81,0x1f40,0xdd01,0x1dc0,0x1c80,0xdc41,0x1400,0xd4c1,0xd581,0x1540,0xd701,0x17c0,0x1680,0xd641,0xd201,0x12c0,0x1380,0xd341,0x1100,0xd1c1,0xd081,0x1040,0xf001,0x30c0,0x3180,0xf141,0x3300,0xf3c1,0xf281,0x3240,0x3600,0xf6c1,0xf781,0x3740,0xf501,0x35c0,0x3480,0xf441,0x3c00,0xfcc1,0xfd81,0x3d40,0xff01,0x3fc0,0x3e80,0xfe41,0xfa01,0x3ac0,0x3b80,0xfb41,0x3900,0xf9c1,0xf881,0x3840,0x2800,0xe8c1,0xe981,0x2940,0xeb01,0x2bc0,0x2a80,0xea41,0xee01,0x2ec0,0x2f80,0xef41,0x2d00,0xedc1,0xec81,0x2c40,0xe401,0x24c0,0x2580,0xe541,0x2700,0xe7c1,0xe681,0x2640,0x2200,0xe2c1,0xe381,0x2340,0xe101,0x21c0,0x2080,0xe041,0xa001,0x60c0,0x6180,0xa141,0x6300,0xa3c1,0xa281,0x6240,0x6600,0xa6c1,0xa781,0x6740,0xa501,0x65c0,0x6480,0xa441,0x6c00,0xacc1,0xad81,0x6d40,0xaf01,0x6fc0,0x6e80,0xae41,0xaa01,0x6ac0,0x6b80,0xab41,0x6900,0xa9c1,0xa881,0x6840,0x7800,0xb8c1,0xb981,0x7940,0xbb01,0x7bc0,0x7a80,0xba41,0xbe01,0x7ec0,0x7f80,0xbf41,0x7d00,0xbdc1,0xbc81,0x7c40,0xb401,0x74c0,0x7580,0xb541,0x7700,0xb7c1,0xb681,0x7640,0x7200,0xb2c1,0xb381,0x7340,0xb101,0x71c0,0x7080,0xb041,0x5000,0x90c1,0x9181,0x5140,0x9301,0x53c0,0x5280,0x9241,0x9601,0x56c0,0x5780,0x9741,0x5500,0x95c1,0x9481,0x5440,0x9c01,0x5cc0,0x5d80,0x9d41,0x5f00,0x9fc1,0x9e81,0x5e40,0x5a00,0x9ac1,0x9b81,0x5b40,0x9901,0x59c0,0x5880,0x9841,0x8801,0x48c0,0x4980,0x8941,0x4b00,0x8bc1,0x8a81,0x4a40,0x4e00,0x8ec1,0x8f81,0x4f40,0x8d01,0x4dc0,0x4c80,0x8c41,0x4400,0x84c1,0x8581,0x4540,0x8701,0x47c0,0x4680,0x8641,0x8201,0x42c0,0x4380,0x8341,0x4100,0x81c1,0x8081,0x4040};
uint32_t morn_crc16_table3[256]={0x0,0x365e,0x6cbc,0x5ae2,0xd978,0xef26,0xb5c4,0x839a,0xff89,0xc9d7,0x9335,0xa56b,0x26f1,0x10af,0x4a4d,0x7c13,0xb26b,0x8435,0xded7,0xe889,0x6b13,0x5d4d,0x7af,0x31f1,0x4de2,0x7bbc,0x215e,0x1700,0x949a,0xa2c4,0xf826,0xce78,0x29af,0x1ff1,0x4513,0x734d,0xf0d7,0xc689,0x9c6b,0xaa35,0xd626,0xe078,0xba9a,0x8cc4,0xf5e,0x3900,0x63e2,0x55bc,0x9bc4,0xad9a,0xf778,0xc126,0x42bc,0x74e2,0x2e00,0x185e,0x644d,0x5213,0x8f1,0x3eaf,0xbd35,0x8b6b,0xd189,0xe7d7,0x535e,0x6500,0x3fe2,0x9bc,0x8a26,0xbc78,0xe69a,0xd0c4,0xacd7,0x9a89,0xc06b,0xf635,0x75af,0x43f1,0x1913,0x2f4d,0xe135,0xd76b,0x8d89,0xbbd7,0x384d,0xe13,0x54f1,0x62af,0x1ebc,0x28e2,0x7200,0x445e,0xc7c4,0xf19a,0xab78,0x9d26,0x7af1,0x4caf,0x164d,0x2013,0xa389,0x95d7,0xcf35,0xf96b,0x8578,0xb326,0xe9c4,0xdf9a,0x5c00,0x6a5e,0x30bc,0x6e2,0xc89a,0xfec4,0xa426,0x9278,0x11e2,0x27bc,0x7d5e,0x4b00,0x3713,0x14d,0x5baf,0x6df1,0xee6b,0xd835,0x82d7,0xb489,0xa6bc,0x90e2,0xca00,0xfc5e,0x7fc4,0x499a,0x1378,0x2526,0x5935,0x6f6b,0x3589,0x3d7,0x804d,0xb613,0xecf1,0xdaaf,0x14d7,0x2289,0x786b,0x4e35,0xcdaf,0xfbf1,0xa113,0x974d,0xeb5e,0xdd00,0x87e2,0xb1bc,0x3226,0x478,0x5e9a,0x68c4,0x8f13,0xb94d,0xe3af,0xd5f1,0x566b,0x6035,0x3ad7,0xc89,0x709a,0x46c4,0x1c26,0x2a78,0xa9e2,0x9fbc,0xc55e,0xf300,0x3d78,0xb26,0x51c4,0x679a,0xe400,0xd25e,0x88bc,0xbee2,0xc2f1,0xf4af,0xae4d,0x9813,0x1b89,0x2dd7,0x7735,0x416b,0xf5e2,0xc3bc,0x995e,0xaf00,0x2c9a,0x1ac4,0x4026,0x7678,0xa6b,0x3c35,0x66d7,0x5089,0xd313,0xe54d,0xbfaf,0x89f1,0x4789,0x71d7,0x2b35,0x1d6b,0x9ef1,0xa8af,0xf24d,0xc413,0xb800,0x8e5e,0xd4bc,0xe2e2,0x6178,0x5726,0xdc4,0x3b9a,0xdc4d,0xea13,0xb0f1,0x86af,0x535,0x336b,0x6989,0x5fd7,0x23c4,0x159a,0x4f78,0x7926,0xfabc,0xcce2,0x9600,0xa05e,0x6e26,0x5878,0x29a,0x34c4,0xb75e,0x8100,0xdbe2,0xedbc,0x91af,0xa7f1,0xfd13,0xcb4d,0x48d7,0x7e89,0x246b,0x1235};
uint32_t morn_crc8_table1[ 256]={0x0,0x91,0xe3,0x72,0x7,0x96,0xe4,0x75,0xe,0x9f,0xed,0x7c,0x9,0x98,0xea,0x7b,0x1c,0x8d,0xff,0x6e,0x1b,0x8a,0xf8,0x69,0x12,0x83,0xf1,0x60,0x15,0x84,0xf6,0x67,0x38,0xa9,0xdb,0x4a,0x3f,0xae,0xdc,0x4d,0x36,0xa7,0xd5,0x44,0x31,0xa0,0xd2,0x43,0x24,0xb5,0xc7,0x56,0x23,0xb2,0xc0,0x51,0x2a,0xbb,0xc9,0x58,0x2d,0xbc,0xce,0x5f,0x70,0xe1,0x93,0x2,0x77,0xe6,0x94,0x5,0x7e,0xef,0x9d,0xc,0x79,0xe8,0x9a,0xb,0x6c,0xfd,0x8f,0x1e,0x6b,0xfa,0x88,0x19,0x62,0xf3,0x81,0x10,0x65,0xf4,0x86,0x17,0x48,0xd9,0xab,0x3a,0x4f,0xde,0xac,0x3d,0x46,0xd7,0xa5,0x34,0x41,0xd0,0xa2,0x33,0x54,0xc5,0xb7,0x26,0x53,0xc2,0xb0,0x21,0x5a,0xcb,0xb9,0x28,0x5d,0xcc,0xbe,0x2f,0xe0,0x71,0x3,0x92,0xe7,0x76,0x4,0x95,0xee,0x7f,0xd,0x9c,0xe9,0x78,0xa,0x9b,0xfc,0x6d,0x1f,0x8e,0xfb,0x6a,0x18,0x89,0xf2,0x63,0x11,0x80,0xf5,0x64,0x16,0x87,0xd8,0x49,0x3b,0xaa,0xdf,0x4e,0x3c,0xad,0xd6,0x47,0x35,0xa4,0xd1,0x40,0x32,0xa3,0xc4,0x55,0x27,0xb6,0xc3,0x52,0x20,0xb1,0xca,0x5b,0x29,0xb8,0xcd,0x5c,0x2e,0xbf,0x90,0x1,0x73,0xe2,0x97,0x6,0x74,0xe5,0x9e,0xf,0x7d,0xec,0x99,0x8,0x7a,0xeb,0x8c,0x1d,0x6f,0xfe,0x8b,0x1a,0x68,0xf9,0x82,0x13,0x61,0xf0,0x85,0x14,0x66,0xf7,0xa8,0x39,0x4b,0xda,0xaf,0x3e,0x4c,0xdd,0xa6,0x37,0x45,0xd4,0xa1,0x30,0x42,0xd3,0xb4,0x25,0x57,0xc6,0xb3,0x22,0x50,0xc1,0xba,0x2b,0x59,0xc8,0xbd,0x2c,0x5e,0xcf};
uint32_t morn_crc8_table2[ 256]={0x0,0x5e,0xbc,0xe2,0x61,0x3f,0xdd,0x83,0xc2,0x9c,0x7e,0x20,0xa3,0xfd,0x1f,0x41,0x9d,0xc3,0x21,0x7f,0xfc,0xa2,0x40,0x1e,0x5f,0x1,0xe3,0xbd,0x3e,0x60,0x82,0xdc,0x23,0x7d,0x9f,0xc1,0x42,0x1c,0xfe,0xa0,0xe1,0xbf,0x5d,0x3,0x80,0xde,0x3c,0x62,0xbe,0xe0,0x2,0x5c,0xdf,0x81,0x63,0x3d,0x7c,0x22,0xc0,0x9e,0x1d,0x43,0xa1,0xff,0x46,0x18,0xfa,0xa4,0x27,0x79,0x9b,0xc5,0x84,0xda,0x38,0x66,0xe5,0xbb,0x59,0x7,0xdb,0x85,0x67,0x39,0xba,0xe4,0x6,0x58,0x19,0x47,0xa5,0xfb,0x78,0x26,0xc4,0x9a,0x65,0x3b,0xd9,0x87,0x4,0x5a,0xb8,0xe6,0xa7,0xf9,0x1b,0x45,0xc6,0x98,0x7a,0x24,0xf8,0xa6,0x44,0x1a,0x99,0xc7,0x25,0x7b,0x3a,0x64,0x86,0xd8,0x5b,0x5,0xe7,0xb9,0x8c,0xd2,0x30,0x6e,0xed,0xb3,0x51,0xf,0x4e,0x10,0xf2,0xac,0x2f,0x71,0x93,0xcd,0x11,0x4f,0xad,0xf3,0x70,0x2e,0xcc,0x92,0xd3,0x8d,0x6f,0x31,0xb2,0xec,0xe,0x50,0xaf,0xf1,0x13,0x4d,0xce,0x90,0x72,0x2c,0x6d,0x33,0xd1,0x8f,0xc,0x52,0xb0,0xee,0x32,0x6c,0x8e,0xd0,0x53,0xd,0xef,0xb1,0xf0,0xae,0x4c,0x12,0x91,0xcf,0x2d,0x73,0xca,0x94,0x76,0x28,0xab,0xf5,0x17,0x49,0x8,0x56,0xb4,0xea,0x69,0x37,0xd5,0x8b,0x57,0x9,0xeb,0xb5,0x36,0x68,0x8a,0xd4,0x95,0xcb,0x29,0x77,0xf4,0xaa,0x48,0x16,0xe9,0xb7,0x55,0xb,0x88,0xd6,0x34,0x6a,0x2b,0x75,0x97,0xc9,0x4a,0x14,0xf6,0xa8,0x74,0x2a,0xc8,0x96,0x15,0x4b,0xa9,0xf7,0xb6,0xe8,0xa,0x54,0xd7,0x89,0x6b,0x35};

void CRCTable(uint32_t *p_poly)
{
    MHandle *hdl = mHandle("CRC",CRC);
    struct HandleCRC *handle = hdl->handle;
    
    uint32_t poly = *p_poly;
    if((poly==handle->poly)&&(handle->bit0==handle->bit)) return;
    handle->poly = poly;
    handle->bit0 =handle->bit;
    
    if(handle->bit==32)
    {
        if(poly==0x04c11db7) {handle->table=morn_crc32_table; return;}
    }
    else if(handle->bit==16)
    {
        if(poly>0x0FFFF) {handle->bit0=0;return;}
        if(poly==0x1021) {handle->table=morn_crc16_table1; return;}
        if(poly==0x8005) {handle->table=morn_crc16_table2; return;}
        if(poly==0x3D65) {handle->table=morn_crc16_table3; return;}
    }
    else if(handle->bit==8)
    {
        if(poly>0x0FF) {handle->bit0=0;return;}
        if(poly==0x07) {handle->table= morn_crc8_table1; return;}
        if(poly==0x31) {handle->table= morn_crc8_table2; return;}
    }
    else mException(1,EXIT,"invalid crc bit(%d)",handle->bit);
    
    handle->table=handle->table0;
    uint32_t var = 0;
    for(int i=0;i<handle->bit;i++,poly=poly>>1) {if(poly & 0x01) var |= 1<<(handle->bit-1-i);}
    
    for(int i=0;i<256;i++)
    {
        uint32_t c = i;
        for (int j=0;j<8;j++)
        {
            if(c&1) c=var^(c>>1);
            else c=c>>1;
        }
        handle->table[i] = c;
        printf("0x%x,",c);
    }
    printf("\n");
}

void CRCType(char *type)
{
    MHandle *hdl = mHandle("CRC",CRC);
    struct HandleCRC *handle = hdl->handle;
    uint32_t poly;
         if(strcmp(type,"CRC32"      )==0) {poly=0x04c11db7;handle->bit=32;handle->init=0xFFFFFFFF;handle->xor=0xFFFFFFFF;handle->endian=LITTLE_ENDIAN;}
    else if(strcmp(type,"MPEG2"      )==0) {poly=0x04c11db7;handle->bit=32;handle->init=0xFFFFFFFF;handle->xor=0         ;handle->endian=   BIG_ENDIAN;}
    else if(strcmp(type,"X25"        )==0) {poly=    0x1021;handle->bit=16;handle->init=0xFFFF    ;handle->xor=0xFFFF    ;handle->endian=LITTLE_ENDIAN;}
    else if(strcmp(type,"CCITT"      )==0) {poly=    0x1021;handle->bit=16;handle->init=0         ;handle->xor=0         ;handle->endian=LITTLE_ENDIAN;}
    else if(strcmp(type,"CCITT-FALSE")==0) {poly=    0x1021;handle->bit=16;handle->init=0xFFFF    ;handle->xor=0         ;handle->endian=   BIG_ENDIAN;}
    else if(strcmp(type,"XMODEM"     )==0) {poly=    0x1021;handle->bit=16;handle->init=0         ;handle->xor=0         ;handle->endian=   BIG_ENDIAN;}
    else if(strcmp(type,"IBM"        )==0) {poly=    0x8005;handle->bit=16;handle->init=0         ;handle->xor=0         ;handle->endian=LITTLE_ENDIAN;}
    else if(strcmp(type,"MAXIM-16"   )==0) {poly=    0x8005;handle->bit=16;handle->init=0         ;handle->xor=0xFFFF    ;handle->endian=LITTLE_ENDIAN;}
    else if(strcmp(type,"USB"        )==0) {poly=    0x8005;handle->bit=16;handle->init=0xFFFF    ;handle->xor=0xFFFF    ;handle->endian=LITTLE_ENDIAN;}
    else if(strcmp(type,"MODEBUS"    )==0) {poly=    0x8005;handle->bit=16;handle->init=0xFFFF    ;handle->xor=0         ;handle->endian=LITTLE_ENDIAN;}
    else if(strcmp(type,"DNP"        )==0) {poly=    0x3D65;handle->bit=16;handle->init=0         ;handle->xor=0xFFFF    ;handle->endian=LITTLE_ENDIAN;}
    else if(strcmp(type,"CRC8"       )==0) {poly=      0x07;handle->bit= 8;handle->init=0         ;handle->xor=0         ;handle->endian=   BIG_ENDIAN;}
    else if(strcmp(type,"ITU"        )==0) {poly=      0x07;handle->bit= 8;handle->init=0         ;handle->xor=0x55      ;handle->endian=   BIG_ENDIAN;}
    else if(strcmp(type,"ROHC"       )==0) {poly=      0x07;handle->bit= 8;handle->init=0xFF      ;handle->xor=0         ;handle->endian=LITTLE_ENDIAN;}
    else if(strcmp(type,"MAXIM-8"    )==0) {poly=      0x31;handle->bit= 8;handle->init=0         ;handle->xor=0         ;handle->endian=LITTLE_ENDIAN;}
    else return;
    CRCTable(&poly);
}

struct HandleCRC *CRCInit()
{
    if(morn_crc_handle!=NULL) return morn_crc_handle;
    MHandle *hdl = mHandle("CRC",CRC);
    struct HandleCRC *handle = hdl->handle;
    if(!mHandleValid(hdl))
    {
        mPropertyFunction("CRC","exit"  ,mornObjectRemove,"CRC");
        mPropertyFunction("CRC","type"  ,CRCType);
        mPropertyFunction("CRC","poly"  ,CRCTable);
        mPropertyVariate( "CRC","bit"   ,&(handle->bit)   ,sizeof(int    ));
        mPropertyVariate( "CRC","init"  ,&(handle->init)  ,sizeof(int32_t));
        mPropertyVariate( "CRC","xor"   ,&(handle->xor )  ,sizeof(int32_t));
        mPropertyVariate( "CRC","endian",&(handle->endian),sizeof(int32_t));
        handle->endian0 = mEndian();
        
        if(handle->poly==0) 
        {
            uint32_t poly =0x04c11db7;
            handle->bit   =32;
            handle->init  =0xFFFFFFFF;
            handle->xor   =0xFFFFFFFF;
            handle->endian=LITTLE_ENDIAN;
            CRCTable(&poly);
        }
        
        hdl->valid=1;
    }
    morn_crc_handle = handle;
    return handle;
}

uint32_t m_CRC(uint8_t* input,int len)
{
    if(len<0) len=strlen((char *)input);
    
    struct HandleCRC *handle = CRCInit();
    if(handle->bit0!=handle->bit) CRCTable(&(handle->poly));
    
    uint32_t *table=handle->table;
    uint32_t init=handle->init,xor=handle->xor;
    if(handle->endian!=handle->endian0) 
    {
        input=ReverseData(input,len);
             if(handle->bit==32) {init=Reverse32(handle->init);xor=Reverse32(handle->xor);}
        else if(handle->bit==16) {init=Reverse16(handle->init);xor=Reverse16(handle->xor);}
        else /*(handle->bit==8)*/{init=Reverse8( handle->init);xor=Reverse8( handle->xor);}
    }
    
    uint32_t crc=init;
    for(int i=0;i<len;i++)
        crc = (crc>>8)^table[(crc^input[i])&0x0FF];
    uint32_t rst = (crc^xor);
    
    if(handle->endian!=handle->endian0) 
    {
             if(handle->bit==32) rst=Reverse32(rst);
        else if(handle->bit==16) rst=Reverse16(rst);
        else /* handle->bit==8*/ rst=Reverse8( rst);
        if(input!=morn_crc_buff) mFree(input);
    }
    return rst;
}
